package com.bn.commerce.order.purchase;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletException;
import javax.transaction.Transaction;

import com.bn.commerce.order.BNCommerceItemImpl;
import com.bn.commerce.order.BNOrderImpl;
import com.bn.commerce.order.BnGiftCardCommerceItemImpl;
import com.bn.commerce.order.BnGiftWrapCommerceItemImpl;
import com.bn.util.BNConstants;

import atg.commerce.CommerceException;
import atg.commerce.inventory.InventoryException;
import atg.commerce.inventory.InventoryManager;
import atg.commerce.order.CommerceItem;
import atg.commerce.order.CommerceItemNotFoundException;
import atg.commerce.order.ElectronicShippingGroup;
import atg.commerce.order.InvalidParameterException;
import atg.commerce.order.Order;
import atg.commerce.order.ShippingGroup;
import atg.commerce.util.RepeatingRequestMonitor;
import atg.droplet.DropletFormException;
import atg.projects.store.BNStoreConfiguration;
import atg.projects.store.order.purchase.StoreCartFormHandler;
import atg.projects.store.order.purchase.StoreCartProcessHelper;
import atg.service.pipeline.RunProcessException;
import atg.servlet.DynamoHttpServletRequest;
import atg.servlet.DynamoHttpServletResponse;


public class BNCartModifierFormHandler extends StoreCartFormHandler
{
	private String commerceItemIdToUpdate;
	private String updatedQuantitySuccessURL;
	private String updatedQuantityErrorURL;
	private String giftWrapSuccessURL;
	private String giftWrapErrorURL;
	private String addGiftNote;
	private boolean giftWrapped;
	private Double enterAmount;
	private String giftCardSuccessURL;
	private String giftCardErrorURL;
	private String recipientEmail;
	private String yourName;
	private boolean isVirtual;
	private BNStoreConfiguration storeConfiguration;
	private static final String BN_GIFTWRAP_COMMERCE_ITEM = "bnGiftWrapCommerceItem";
	private static final String GIFT_CARD_COMMERCEITEM = "bnGiftCardCommerceItem";
	private static final String GIFT_WRAP_PROD_ID = "prodId";
	private static final String GIFT_WRAP_SKU_ID = "skuId";
	private static final String GIFT_CARD_PROD_ID = "gcProdId";
	private static final String GIFT_CARD_SKU_ID = "gcSkuId";
	private static final String ELECTRONIC_SHIPPING_GROUP = "electronicShippingGroup";
	private static final String INVENTORY_ERROR_KEY = "errorKey";
	private boolean updateGiftCard;
	private String updatedElectronicGCSuccessURL;
	private String updatedElectronicGCErrorURL;
	private String updatedPhysicalGCSuccessURL;
	private String updatedPhysicalGCErrorURL;

	@Override
	public void preAddItemToOrder(DynamoHttpServletRequest pRequest,
			DynamoHttpServletResponse pResponse) throws ServletException,
			IOException {
		for (String skuId : getCatalogRefIds())
		{
			boolean isSkuQuantityAvailable = isSkuQuantityAvailableForUpdate(skuId, getQuantity(skuId, pRequest, pResponse));
			if (!isSkuQuantityAvailable) {
				formatAndAddErrorMessage("addItemInventoryError", "", pRequest, pResponse);
			}
		}

		super.preAddItemToOrder(pRequest, pResponse);
	}


	  public boolean handleRemoveItemFromOrder(DynamoHttpServletRequest pRequest, DynamoHttpServletResponse pResponse)
			       throws IOException, ServletException
 {
		RepeatingRequestMonitor rrm = getRepeatingRequestMonitor();
		String myHandleMethod = "CartModifierOrderFormHandler.handleRemoveItemFromOrder";

		if ((rrm == null) || (rrm.isUniqueRequestEntry(myHandleMethod))) {
			Transaction tr = null;
			try {
				tr = super.ensureTransaction();

				if (getUserLocale() == null) {
					setUserLocale(getUserLocale(pRequest, pResponse));
				}

				if (!(checkFormRedirect(null, getRemoveItemFromOrderErrorURL(),
						pRequest, pResponse))) {
					return false;
				}
				synchronized (getOrder()) {
					preRemoveItemFromOrder(pRequest, pResponse);

					if (!(checkFormRedirect(null,
							getRemoveItemFromOrderErrorURL(), pRequest,
							pResponse))) {
						int j = 0;

						if (tr != null) {
							commitTransaction(tr);
						}
						if (rrm != null)
							rrm.removeRequestEntry(myHandleMethod);
						return false;
					}
					if (getRemovalCommerceIds() != null) {
						Map extraParams;
						try {
							deleteItems(pRequest, pResponse);
							extraParams = createRepriceParameterMap();
						} catch (Exception exc) {
							processException(exc, "errorUpdatingOrder",
									pRequest, pResponse);
						}
					}
					if (!(checkFormRedirect(null,
							getRemoveItemFromOrderErrorURL(), pRequest,
							pResponse))) {

						if (tr != null) {
							commitTransaction(tr);
						}
						if (rrm != null)
							rrm.removeRequestEntry(myHandleMethod);
						return false;
					}
					postRemoveItemFromOrder(pRequest, pResponse);

					Order order = getOrder();
					Map removedItemMap = new HashMap();
					Map changedItemMap = new HashMap();
					Map extraParams = createRepriceParameterMap();
					try {
						runProcessRepriceOrder(getModifyOrderPricingOp(), order,
								getUserPricingModels(), getUserLocale(),
								getProfile(), extraParams);
					} catch (RunProcessException e) {
						if(isLoggingError()){
							logError("Exception while creating giftwrap :",e);
					}
					} try {
						modifyOrderPostReprice(pRequest, pResponse, changedItemMap,
								removedItemMap);
					} catch (RunProcessException Re) {
						if(isLoggingError()){
							logError("Exception while creating giftwrap :",Re);
						}
					} catch (CommerceException Ce) {
						if(isLoggingError()){
							logError("Exception while creating giftwrap :",Ce);
						}
					}

					updateOrder(getOrder(), "errorUpdatingOrder", pRequest,
							pResponse);
				}

				boolean bool = checkFormRedirect(
						getRemoveItemFromOrderSuccessURL(),
						getRemoveItemFromOrderErrorURL(), pRequest, pResponse);

				return bool;
			} finally {
				if (tr != null) {
					commitTransaction(tr);
				}
				if (rrm != null) {
					rrm.removeRequestEntry(myHandleMethod);
				}
			}
		}

		return false;
	}

	  @Override
	public void postRemoveItemFromOrder(DynamoHttpServletRequest arg0,
			DynamoHttpServletResponse arg1) throws ServletException,
			IOException {
		super.postRemoveItemFromOrder(arg0, arg1);
		updateGiftWrapQuantity();
	}

public boolean handleUpdateQuantity(DynamoHttpServletRequest pRequest, DynamoHttpServletResponse pResponse) throws ServletException, IOException {
		System.out.println("hand;le");

		if (getOrder() == null) {
			formatAndAddErrorMessage("noOrderToModify", "", pRequest, pResponse);
		}
		String updatedCommerceItemId = getCommerceItemIdToUpdate();
		long quantity = getQuantity();
		if (updatedCommerceItemId == null || quantity <= 0L) {
			formatAndAddErrorMessage("errorUpdateQty", "", pRequest, pResponse);
		}
		if (getFormError()) {
			return checkFormRedirect(getRemoveAndAddItemToOrderSuccessURL(), getRemoveAndAddItemToOrderErrorURL(), pRequest, pResponse);
		}

		CommerceItem updatedCommerceItem = null;
		RepeatingRequestMonitor rrm = getRepeatingRequestMonitor();
		String myHandleMethod = "BNCartModifierFormHandler.handleUpdateQuantity";

		if ((rrm == null) || (rrm.isUniqueRequestEntry(myHandleMethod))) {
			Transaction tr = null;

			try {
				tr = ensureTransaction();

				if (getUserLocale() == null) {
					setUserLocale(getUserLocale(pRequest, pResponse));
				}

				updatedCommerceItem = getOrder().getCommerceItem(getCommerceItemIdToUpdate());

				if (updatedCommerceItem == null || updatedCommerceItem.getCatalogRefId() == null) {
					formatAndAddErrorMessage("errorUpdateQty", "", pRequest, pResponse);
				}

				if (getFormError()) {
					return checkFormRedirect(getRemoveAndAddItemToOrderSuccessURL(), getRemoveAndAddItemToOrderErrorURL(), pRequest, pResponse);
				}


				if(updatedCommerceItem.getQuantity() == getQuantity()){
					return checkFormRedirect(getRemoveAndAddItemToOrderSuccessURL(), getRemoveAndAddItemToOrderErrorURL(), pRequest, pResponse);
				}

				preUpdateQuantity(updatedCommerceItem.getCatalogRefId(), quantity, pRequest, pResponse);

				if (getFormError()) {
					return checkFormRedirect(getRemoveAndAddItemToOrderSuccessURL(), getRemoveAndAddItemToOrderErrorURL(), pRequest, pResponse);
				}

				synchronized (getOrder()) {
					if (!getFormError()) {
						modifyOrderByUpdatedQty(updatedCommerceItem, quantity);
					}
					postUpdateQuantity();
					Order order = getOrder();
					Map removedItemMap = new HashMap();
					Map changedItemMap = new HashMap();
					Map extraParams = createRepriceParameterMap();
					runProcessRepriceOrder(getModifyOrderPricingOp(), order,
							getUserPricingModels(), getUserLocale(),
							getProfile(), extraParams);
					modifyOrderPostReprice(pRequest, pResponse, changedItemMap,
							removedItemMap);

					updateOrder(getOrder(), MSG_ERROR_UPDATE_ORDER, pRequest,
							pResponse);
				}

			} catch (CommerceException ce) {
				processException(ce, StoreCartProcessHelper.MSG_ERROR_MODIFYING_ORDER, pRequest, pResponse);
			} catch (RunProcessException re) {
				processException(re, StoreCartProcessHelper.MSG_ERROR_MODIFYING_ORDER, pRequest, pResponse);
			} finally {
				if (tr != null) {
					commitTransaction(tr);
				}

				if (rrm != null) {
					rrm.removeRequestEntry(myHandleMethod);
				}
			}
		}

		return checkFormRedirect(getRemoveAndAddItemToOrderSuccessURL(), getRemoveAndAddItemToOrderErrorURL(), pRequest, pResponse);
	}

	private void postUpdateQuantity (){
		updateGiftWrapQuantity ();
	}

	private void updateGiftWrapQuantity (){
		List<BNCommerceItemImpl> commerceItems = getOrder().getCommerceItems();
		long Qty = 0;
		for (BNCommerceItemImpl item : commerceItems){
			if(item instanceof BnGiftWrapCommerceItemImpl){
				continue;
			}
			boolean isGiftWrapped = item.isGiftWrapped();
			if(isGiftWrapped){
				BNOrderImpl orderImpl = (BNOrderImpl) getOrder();
				BnGiftWrapCommerceItemImpl bnGiftWrapCommerceItemImpl = orderImpl.getGiftWrap();
				Qty = Qty + item.getQuantity();
				try {
					modifyOrderByUpdatedQty(bnGiftWrapCommerceItemImpl, Qty);
					bnGiftWrapCommerceItemImpl.setQuantity(Qty);
				} catch (RunProcessException e) {
					if(isLoggingError()){
						logError("Exception while creating giftwrap :",e);
					}
				} catch (CommerceException e) {
					if(isLoggingError()){
						logError("Exception while creating giftwrap :",e);
					}
				} catch (ServletException e) {
					if(isLoggingError()){
						logError("Exception while creating giftwrap :",e);
					}
				} catch (IOException e) {
					if(isLoggingError()){
						logError("Exception while creating giftwrap :",e);
					}
				}

			}
		}
	}


public boolean handleAddGiftCard(DynamoHttpServletRequest pRequest, DynamoHttpServletResponse pResponse) throws ServletException, IOException {

	if (getOrder() == null) {
		formatAndAddErrorMessage("noOrderToModify", "", pRequest, pResponse);
	}

	if (getFormError()) {
		return checkFormRedirect(getGiftCardSuccessURL(), getGiftCardErrorURL(), pRequest, pResponse);
	}


	RepeatingRequestMonitor rrm = getRepeatingRequestMonitor();
	String myHandleMethod = "BNCartModifierFormHandler.handleAddGiftCard";

	if ((rrm == null) || (rrm.isUniqueRequestEntry(myHandleMethod))) {
		Transaction tr = null;

		try {
			tr = ensureTransaction();

			if (getUserLocale() == null) {
				setUserLocale(getUserLocale(pRequest, pResponse));
			}

			synchronized (getOrder()) {
				if (!getFormError()) {
							addGiftCardItem ();
				}
				updateOrder(getOrder(), MSG_ERROR_UPDATE_ORDER, pRequest, pResponse);
				Map extraParams = createRepriceParameterMap();
				try {
					runProcessRepriceOrder(getModifyOrderPricingOp(), getOrder(), getUserPricingModels(), getUserLocale(), getProfile(), extraParams);
				} catch(RunProcessException e){
					if(isLoggingError()){
						logError("Exception while creating giftwrap :",e);
					}
				}
			}


		} finally {
			if (tr != null) {
				commitTransaction(tr);
			}

			if (rrm != null) {
				rrm.removeRequestEntry(myHandleMethod);
			}
		}
	}

	 return  checkFormRedirect(getGiftCardSuccessURL(), getGiftCardErrorURL(), pRequest, pResponse);
}


public boolean handleUpdateGiftCard(DynamoHttpServletRequest pRequest, DynamoHttpServletResponse pResponse) throws ServletException, IOException {

	if (getOrder() == null) {
		formatAndAddErrorMessage("noOrderToModify", "", pRequest, pResponse);
	}
	String updatedCommerceItemId = getCommerceItemIdToUpdate();
	if (updatedCommerceItemId == null) {
		formatAndAddErrorMessage("errorUpdateQty", "", pRequest, pResponse);
	}
	if (getFormError()) {
		return checkFormRedirect(getUpdateSuccessURL(), getUpdateErrorURL(), pRequest, pResponse);
	}

	RepeatingRequestMonitor rrm = getRepeatingRequestMonitor();
	String myHandleMethod = "BNCartModifierFormHandler.handleUpdateGiftCard";

	if ((rrm == null) || (rrm.isUniqueRequestEntry(myHandleMethod))) {
		Transaction tr = null;

		try {
			tr = ensureTransaction();

			if (getUserLocale() == null) {
				setUserLocale(getUserLocale(pRequest, pResponse));
			}


			if (getFormError()) {
				return checkFormRedirect(getUpdateSuccessURL(), getUpdateErrorURL(), pRequest, pResponse);
			}

			synchronized (getOrder()) {
				if (!getFormError()) {
					updateGiftCardItem(updatedCommerceItemId);
				}
				updateOrder(getOrder(), MSG_ERROR_UPDATE_ORDER, pRequest, pResponse);
				Map extraParams = createRepriceParameterMap();
				try {
					runProcessRepriceOrder(getModifyOrderPricingOp(), getOrder(), getUserPricingModels(), getUserLocale(), getProfile(), extraParams);
				} catch(RunProcessException e){
					if(isLoggingError()){
						logError("Exception while creating giftwrap :",e);
					}
				}
			}

		} catch (Exception ce) {
			processException(ce, StoreCartProcessHelper.MSG_ERROR_MODIFYING_ORDER, pRequest, pResponse);
		} finally {
			if (tr != null) {
				commitTransaction(tr);
			}

			if (rrm != null) {
				rrm.removeRequestEntry(myHandleMethod);
			}
		}
	}

	return checkFormRedirect(getUpdateSuccessURL(), getUpdateErrorURL(), pRequest, pResponse);
}

private void updateGiftCardItem(String updatedCommerceItemId) {
	try {
		BnGiftCardCommerceItemImpl updatedCommerceItem = (BnGiftCardCommerceItemImpl) getOrder().getCommerceItem(updatedCommerceItemId);
		if(isVirtual){
			updatedCommerceItem.setRecpientEmail(recipientEmail);
			updatedCommerceItem.setYourName(yourName);
			updatedCommerceItem.setVirtual(isVirtual);
		}
		updatedCommerceItem.setUserEnteredAmount(enterAmount);
		updatedCommerceItem.setGiftMsg(addGiftNote);
	} catch (CommerceItemNotFoundException e) {
		if(isLoggingError()){
			logError("Exception while updating giftCard :",e);
		}
	} catch (InvalidParameterException e) {
		if(isLoggingError()){
			logError("Exception while updating giftCard :",e);
		}
	}
}


private void addGiftCardItem() {
	Map<String,String>  giftCardKeyMap = getStoreConfiguration().getGiftCardKeyMap();
	try {
			BnGiftCardCommerceItemImpl bnGiftCardCommerceItemImpl = (BnGiftCardCommerceItemImpl)getCommerceItemManager().createCommerceItem(GIFT_CARD_COMMERCEITEM, giftCardKeyMap.get(GIFT_CARD_SKU_ID),giftCardKeyMap.get(GIFT_CARD_PROD_ID), getQuantity());
			getCommerceItemManager().addAsSeparateItemToOrder(getOrder(), bnGiftCardCommerceItemImpl);
			ShippingGroup sg = null;
			if(isVirtual){
				bnGiftCardCommerceItemImpl.setUserEnteredAmount(enterAmount);
				bnGiftCardCommerceItemImpl.setGiftMsg(addGiftNote);
				bnGiftCardCommerceItemImpl.setQuantity(getQuantity());
				bnGiftCardCommerceItemImpl.setRecpientEmail(recipientEmail);
				bnGiftCardCommerceItemImpl.setYourName(yourName);
				bnGiftCardCommerceItemImpl.setVirtual(isVirtual);
				sg = getShippingGroupManager().createShippingGroup(ELECTRONIC_SHIPPING_GROUP);
				ElectronicShippingGroup eSG = (ElectronicShippingGroup)sg;
				eSG.setEmailAddress(recipientEmail);
				getShippingGroupManager().addShippingGroupToOrder(getOrder(), sg);
			}else{
				bnGiftCardCommerceItemImpl.setUserEnteredAmount(enterAmount);
				bnGiftCardCommerceItemImpl.setGiftMsg(addGiftNote);
				bnGiftCardCommerceItemImpl.setQuantity(getQuantity());
				sg = (ShippingGroup) getOrder().getShippingGroups().get(0);
			}
			getCommerceItemManager().addItemQuantityToShippingGroup(getOrder(), bnGiftCardCommerceItemImpl.getId(), sg.getId(), getQuantity());
	}
	catch (CommerceException e) {
		if(isLoggingError()){
			logError("Exception while creating giftwrap :",e);
		}
	}
}


	private void addGiftWrap(long quantity) {

		Map<String,String>  giftWrapMap = getStoreConfiguration().getGiftWrapKeyMap();
		try {
			BNOrderImpl bnOrderImpl = (BNOrderImpl)getOrder();
			BnGiftWrapCommerceItemImpl giftWrapCommerceItemImpl = bnOrderImpl.getGiftWrap();
			if(null == giftWrapCommerceItemImpl){
				 giftWrapCommerceItemImpl = (BnGiftWrapCommerceItemImpl)getCommerceItemManager().createCommerceItem(BN_GIFTWRAP_COMMERCE_ITEM, giftWrapMap.get(GIFT_WRAP_SKU_ID),giftWrapMap.get(GIFT_WRAP_PROD_ID), quantity);
				getCommerceItemManager().addItemToOrder(getOrder(), giftWrapCommerceItemImpl);
				ShippingGroup sg= (ShippingGroup) getOrder().getShippingGroups().get(0);
				getCommerceItemManager().addItemQuantityToShippingGroup(getOrder(), giftWrapCommerceItemImpl.getId(), sg.getId(), quantity);
			}else{
				long giftQty = giftWrapCommerceItemImpl.getQuantity();
				giftWrapCommerceItemImpl.setQuantity(giftQty + quantity);
			}

		}
		catch (CommerceException e) {
			if(isLoggingError()){
				logError("Exception while creating giftwrap :",e);
			}
		}
}

	private void removeGiftWrapQty (long quantity) throws CommerceException{
		BNOrderImpl bnOrderImpl = (BNOrderImpl)getOrder();
		BnGiftWrapCommerceItemImpl giftWrapCommerceItemImpl = bnOrderImpl.getGiftWrap();
		long giftQty = giftWrapCommerceItemImpl.getQuantity();
		if(giftQty > quantity){
			giftWrapCommerceItemImpl.setQuantity(giftQty - quantity);
		}else{
			getCommerceItemManager().removeAllRelationshipsFromCommerceItem(bnOrderImpl, giftWrapCommerceItemImpl.getId());
			getCommerceItemManager().removeItemFromOrder(bnOrderImpl, giftWrapCommerceItemImpl.getId());
		}
	}


	protected void preUpdateQuantity(String skuId, long quantity, DynamoHttpServletRequest request, DynamoHttpServletResponse response) throws ServletException, IOException {

			boolean isSkuQuantityAvailable = isSkuQuantityAvailableForUpdate(skuId, quantity);
			if (!isSkuQuantityAvailable) {
				formatAndAddErrorMessage("addItemInventoryError", "", request, response);
			}
	}

	protected boolean isSkuQuantityAvailableForUpdate(String skuId, long quantity) {

		vlogDebug("Checking inventory quantity for sku ID : " + skuId);
		if (this.getOrderManager() != null && this.getOrderManager().getOrderTools() != null) {
			InventoryManager invManager = this.getOrderManager().getOrderTools().getInventoryManager();
			if (invManager != null) {
				try {
					int status = invManager.queryAvailabilityStatus(skuId);
					vlogDebug("status : " + status);
					if (status != InventoryManager.AVAILABILITY_STATUS_IN_STOCK && status != InventoryManager.AVAILABILITY_STATUS_BACKORDERABLE
							&& status != InventoryManager.AVAILABILITY_STATUS_PREORDERABLE) {
						return false;
					}
					long stockLevel = invManager.queryStockLevel(skuId);
					vlogDebug("stockLevel : " + stockLevel);
					long backOrderLevel = invManager.queryBackorderLevel(skuId);
					vlogDebug("backOrderLevel : " + backOrderLevel);
					long preOrderLevel = invManager.queryPreorderLevel(skuId);
					vlogDebug("preOrderLevel : " + preOrderLevel);
					long availQuantity = stockLevel + backOrderLevel + preOrderLevel;
					vlogDebug("availQuantity : " + availQuantity);
					vlogDebug("quantity : " + quantity);
					if(availQuantity == -1){
						return true;
					}

					return availQuantity >= quantity ? true : false;
				} catch (InventoryException e) {
					logError("InventoryException while adding skuId " + skuId, e);
					return false;
				}
			}
		}
		return false;
	}



protected void modifyOrderByUpdatedQty(CommerceItem item, long quantity) throws ServletException, IOException,
			CommerceException, RunProcessException {

		Order order = getOrder();

		if (quantity > 0L) {

				getPurchaseProcessHelper().adjustItemRelationshipsForQuantityChange(order, item, quantity);
				item.setQuantity(quantity);

		}

	}


public void formatAndAddErrorMessage(String errorKey, String property, DynamoHttpServletRequest request, DynamoHttpServletResponse response) throws ServletException, IOException {

		String msg = formatUserMessage(errorKey, request, response);
		String propertyPath = generatePropertyPath(property);
		addFormException(new DropletFormException(msg, propertyPath, errorKey));
	}



public boolean handleUpdateGiftWrap(DynamoHttpServletRequest pRequest, DynamoHttpServletResponse pResponse) throws ServletException, IOException {

	if (getOrder() == null) {
		formatAndAddErrorMessage("noOrderToModify", "", pRequest, pResponse);
	}
	String updatedCommerceItemId = getCommerceItemIdToUpdate();
	if (updatedCommerceItemId == null) {
		formatAndAddErrorMessage("errorUpdateQty", "", pRequest, pResponse);
	}
	if (getFormError()) {
		return checkFormRedirect(getGiftWrapSuccessURL(), getGiftWrapErrorURL(), pRequest, pResponse);
	}

	BNCommerceItemImpl updatedCommerceItem = null;
	RepeatingRequestMonitor rrm = getRepeatingRequestMonitor();
	String myHandleMethod = "BNCartModifierFormHandler.handleUpdateGiftQuantity";

	if ((rrm == null) || (rrm.isUniqueRequestEntry(myHandleMethod))) {
		Transaction tr = null;

		try {
			tr = ensureTransaction();

			if (getUserLocale() == null) {
				setUserLocale(getUserLocale(pRequest, pResponse));
			}

			updatedCommerceItem = (BNCommerceItemImpl) getOrder().getCommerceItem(getCommerceItemIdToUpdate());

			if (updatedCommerceItem == null || updatedCommerceItem.getCatalogRefId() == null) {
				formatAndAddErrorMessage("errorUpdateQty", "", pRequest, pResponse);
			}

			synchronized (getOrder()) {
				if (!getFormError()) {
					updatedCommerceItem.setGiftNote(addGiftNote);
					updatedCommerceItem.setGiftWrapped(giftWrapped);
					if(giftWrapped){
						addGiftWrap (updatedCommerceItem.getQuantity());
					}else{
						removeGiftWrapQty (updatedCommerceItem.getQuantity());
					}
				}
				updateOrder(getOrder(), MSG_ERROR_UPDATE_ORDER, pRequest, pResponse);
				Map extraParams = createRepriceParameterMap();
				try {
					runProcessRepriceOrder(getModifyOrderPricingOp(), getOrder(), getUserPricingModels(), getUserLocale(), getProfile(), extraParams);
				} catch(RunProcessException e){
					if(isLoggingError()){
						logError("Exception while creating giftwrap :",e);
					}
				}
			}


		} catch (CommerceException ce) {
			processException(ce, StoreCartProcessHelper.MSG_ERROR_MODIFYING_ORDER, pRequest, pResponse);
		}finally {
			if (tr != null) {
				commitTransaction(tr);
			}

			if (rrm != null) {
				rrm.removeRequestEntry(myHandleMethod);
			}
		}
	}

	 return checkFormRedirect(getGiftWrapSuccessURL(), getGiftWrapErrorURL(), pRequest, pResponse);
}

public boolean handleRemoveGiftCard(DynamoHttpServletRequest pRequest, DynamoHttpServletResponse pResponse) throws ServletException, IOException {

	if (getOrder() == null) {
		formatAndAddErrorMessage("noOrderToModify", "", pRequest, pResponse);
	}
	String updatedCommerceItemId = getCommerceItemIdToUpdate();
	if (updatedCommerceItemId == null) {
		formatAndAddErrorMessage("errorUpdateQty", "", pRequest, pResponse);
	}
	if (getFormError()) {
		return checkFormRedirect(getGiftCardSuccessURL(), getGiftCardErrorURL(), pRequest, pResponse);
	}

	BnGiftCardCommerceItemImpl updatedCommerceItem = null;
	RepeatingRequestMonitor rrm = getRepeatingRequestMonitor();
	String myHandleMethod = "BNCartModifierFormHandler.handleRemoveGiftWrap";

	if ((rrm == null) || (rrm.isUniqueRequestEntry(myHandleMethod))) {
		Transaction tr = null;

		try {
			tr = ensureTransaction();

			if (getUserLocale() == null) {
				setUserLocale(getUserLocale(pRequest, pResponse));
			}

			updatedCommerceItem = (BnGiftCardCommerceItemImpl) getOrder().getCommerceItem(getCommerceItemIdToUpdate());

			if (updatedCommerceItem == null) {
				formatAndAddErrorMessage("errorUpdateQty", "", pRequest, pResponse);
			}

			synchronized (getOrder()) {
				if (!getFormError()) {
						removeGiftCard ();
				}
				updateOrder(getOrder(), MSG_ERROR_UPDATE_ORDER, pRequest, pResponse);
				Map extraParams = createRepriceParameterMap();
				try {
					runProcessRepriceOrder(getModifyOrderPricingOp(), getOrder(), getUserPricingModels(), getUserLocale(), getProfile(), extraParams);
				} catch(RunProcessException e){
					if(isLoggingError()){
						logError("Exception while creating giftwrap :",e);
					}
				}
			}


		} catch (CommerceException ce) {
			processException(ce, StoreCartProcessHelper.MSG_ERROR_MODIFYING_ORDER, pRequest, pResponse);
		}finally {
			if (tr != null) {
				commitTransaction(tr);
			}

			if (rrm != null) {
				rrm.removeRequestEntry(myHandleMethod);
			}
		}
	}

	 return checkFormRedirect(getGiftCardSuccessURL(), getGiftCardErrorURL(), pRequest, pResponse);
}



private void removeGiftCard() throws CommerceException {
	BNOrderImpl bnOrderImpl = (BNOrderImpl)getOrder();
	BnGiftCardCommerceItemImpl bnGiftCardCommerceItemImpl = bnOrderImpl.getGiftCard();
	getCommerceItemManager().removeAllRelationshipsFromCommerceItem(bnOrderImpl, bnGiftCardCommerceItemImpl.getId());
	getCommerceItemManager().removeItemFromOrder(bnOrderImpl, bnGiftCardCommerceItemImpl.getId());
}

@Override
public boolean handleCheckout(DynamoHttpServletRequest pRequest, DynamoHttpServletResponse pResponse) throws ServletException, IOException
{

    Order order = getOrder();
    if(null == order.getCommerceItems() || 0 == order.getCommerceItems().size())
    {
        formatAndAddErrorMessage(BNConstants.ERR_NO_ITEMS_IN_CART, "", pRequest, pResponse);
        vlogError(BNConstants.ERR_NO_ITEMS_IN_CART);
        return checkFormRedirect(getMoveToPurchaseInfoSuccessURL(), getMoveToPurchaseInfoErrorURL(), pRequest, pResponse);
    }


    final List<String> errorKeys = checkOrderItemsAvailability(order);
    if(null != errorKeys && !errorKeys.isEmpty())
    {
        for(String INVENTORY_ERROR_KEY : errorKeys)
        {
            formatAndAddErrorMessage(INVENTORY_ERROR_KEY, "", pRequest, pResponse);
        }

		return checkFormRedirect(getMoveToPurchaseInfoSuccessURL(), getMoveToPurchaseInfoErrorURL(), pRequest, pResponse);
    }
    BNPurchaseProcessorHelper purchaseProcessHelper = (BNPurchaseProcessorHelper)getPurchaseProcessHelper();
    boolean isEligibleForExpressCheckout = purchaseProcessHelper.isEligibleForExpressCheckout(getProfile());
    if(isEligibleForExpressCheckout) {

    	vlogDebug("User is eligible for express checkout");
    	return handleExpressCheckout(pRequest, pResponse);
    }else{
    	 super.handleMoveToPurchaseInfoByCommerceId(pRequest, pResponse);
    }

    return checkFormRedirect(getMoveToPurchaseInfoSuccessURL(), getMoveToPurchaseInfoErrorURL(), pRequest, pResponse);

}

private List<String>  checkOrderItemsAvailability (Order pOrder){
	List<String> errors = new ArrayList<String>();

    List<CommerceItem> lCommerceItems = pOrder.getCommerceItems();
    if(null == lCommerceItems || 0 == lCommerceItems.size())
    {
        String errorMessage = BNConstants.ERR_NO_ITEMS_IN_CART;
        errors.add(errorMessage);
        return errors;
    }

    for(CommerceItem lCommerceItem : lCommerceItems)
    {
        final String lSkuId = lCommerceItem.getCatalogRefId();
        final String lProductId = lCommerceItem.getAuxiliaryData().getProductId();
        final long lQuantity = lCommerceItem.getQuantity();

        if(null == lSkuId || null == lProductId)
        {
            String errorMessage = BNConstants.ERR_NO_SKU_OR_PRODUCT_ON_ORDER_ITEM;
            errors.add(errorMessage);
            break;
        }
        boolean isSkuQuantityAvavilable = isSkuQuantityAvailableForUpdate(lSkuId,lQuantity);
        if (!isSkuQuantityAvavilable) {
        	String errorMessage = BNConstants.ERR_FAILED_INVENTORY_CHECK;
            errors.add(errorMessage);
            break;
		}
    }
    return errors;
}


public String getCommerceItemIdToUpdate() {
	return commerceItemIdToUpdate;
}

public void setCommerceItemIdToUpdate(String commerceItemIdToUpdate) {
	this.commerceItemIdToUpdate = commerceItemIdToUpdate;
}

public String getUpdatedQuantityErrorURL() {
	return updatedQuantityErrorURL;
}

public void setUpdatedQuantityErrorURL(String updatedQuantityErrorURL) {
	this.updatedQuantityErrorURL = updatedQuantityErrorURL;
}


public String getGiftWrapSuccessURL() {
	return giftWrapSuccessURL;
}


public void setGiftWrapSuccessURL(String giftWrapSuccessURL) {
	this.giftWrapSuccessURL = giftWrapSuccessURL;
}


public String getGiftWrapErrorURL() {
	return giftWrapErrorURL;
}


public void setGiftWrapErrorURL(String giftWrapErrorURL) {
	this.giftWrapErrorURL = giftWrapErrorURL;
}


public String getAddGiftNote() {
	return addGiftNote;
}


public void setAddGiftNote(String addGiftNote) {
	this.addGiftNote = addGiftNote;
}


public boolean isGiftWrapped() {
	return giftWrapped;
}


public void setGiftWrapped(boolean giftWrapped) {
	this.giftWrapped = giftWrapped;
}


public BNStoreConfiguration getStoreConfiguration() {
	return storeConfiguration;
}


public void setStoreConfiguration(BNStoreConfiguration storeConfiguration) {
	this.storeConfiguration = storeConfiguration;
}


public Double getEnterAmount() {
	return enterAmount;
}


public void setEnterAmount(Double enterAmount) {
	this.enterAmount = enterAmount;
}


public String getGiftCardSuccessURL() {
	return giftCardSuccessURL;
}


public void setGiftCardSuccessURL(String giftCardSuccessURL) {
	this.giftCardSuccessURL = giftCardSuccessURL;
}


public String getGiftCardErrorURL() {
	return giftCardErrorURL;
}


public void setGiftCardErrorURL(String giftCardErrorURL) {
	this.giftCardErrorURL = giftCardErrorURL;
}


public String getRecipientEmail() {
	return recipientEmail;
}


public void setRecipientEmail(String recipientEmail) {
	this.recipientEmail = recipientEmail;
}


public String getYourName() {
	return yourName;
}


public void setYourName(String yourName) {
	this.yourName = yourName;
}


public boolean isVirtual() {
	return isVirtual;
}


public void setVirtual(boolean isVirtual) {
	this.isVirtual = isVirtual;
}


public boolean isUpdateGiftCard() {
	return updateGiftCard;
}


public void setUpdateGiftCard(boolean updateGiftCard) {
	this.updateGiftCard = updateGiftCard;
}


public String getUpdatedElectronicGCSuccessURL() {
	return updatedElectronicGCSuccessURL;
}


public void setUpdatedElectronicGCSuccessURL(
		String updatedElectronicGCSuccessURL) {
	this.updatedElectronicGCSuccessURL = updatedElectronicGCSuccessURL;
}


public String getUpdatedElectronicGCErrorURL() {
	return updatedElectronicGCErrorURL;
}


public void setUpdatedElectronicGCErrorURL(String updatedElectronicGCErrorURL) {
	this.updatedElectronicGCErrorURL = updatedElectronicGCErrorURL;
}


public String getUpdatedPhysicalGCSuccessURL() {
	return updatedPhysicalGCSuccessURL;
}


public void setUpdatedPhysicalGCSuccessURL(String updatedPhysicalGCSuccessURL) {
	this.updatedPhysicalGCSuccessURL = updatedPhysicalGCSuccessURL;
}


public String getUpdatedPhysicalGCErrorURL() {
	return updatedPhysicalGCErrorURL;
}


public void setUpdatedPhysicalGCErrorURL(String updatedPhysicalGCErrorURL) {
	this.updatedPhysicalGCErrorURL = updatedPhysicalGCErrorURL;
}
}
